# -*- encoding:utf-8 -*-
# @Time : 2025/3/16 20:15
# @Author : xunter
# @Email : 3133739348@qq.com
# @File : serializers.py
# @Software : PyCharm
from datetime import datetime
from decimal import Decimal
from random import randint

from django.db import transaction
from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from rest_framework.serializers import ModelSerializer

from shopping.models import Classification, Commodity, CommodityImg, ShoppingCart, Order, OrderGoods, Payment
from users.models import Address


class ClassificationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classification
        fields = ['id', 'name']

class ParentClassificationSerializer(serializers.ModelSerializer):
    classification_set = ClassificationSerializer(many=True, read_only=True)
    class Meta:
        model = Classification
        fields = ['id', 'name','classification_set']

class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = ['src']

class CommoditySerializer(serializers.ModelSerializer):
    classification1_name = serializers.CharField(source='classification1.name', read_only=True)
    classification2_name = serializers.CharField(source='classification2.name', read_only=True)
    commodityimg_set = CommodityImgSerializer(many=True, read_only=True)
    class Meta:
        model = Commodity
        exclude=['is_delete']

        extra_kwargs = {
            'sales':{'read_only':True},
            'comment':{'read_only':True},
        }

class ShoppingCartSerializer(ModelSerializer):
    # 添加商品详情信息  自定义方法完成对应的逻辑返回对应的数据  把当前的模型对象(ShoppingCart)传入到自定义的方法中
    commodityDetail = SerializerMethodField()
    class Meta:
        model = ShoppingCart
        fields = '__all__'

    def validate(self, attrs):
        """
        校验商品数量
        :param attrs:
        :return:
        """
        if attrs['number'] <= 0:
            raise serializers.ValidationError('购买的商品数量')
        elif attrs['number'] > attrs['commodity'].stock:
            raise serializers.ValidationError('数量超出库存')
        else:
            return attrs

    def get_commodityDetail(self, shoppingcart):

        return CommoditySerializer(shoppingcart.commodity).data

class OrderSerializer(ModelSerializer): # 订单
    # 客户端要传入要结算的购物车中的商品列表进行结算
    cart = serializers.ListField(write_only=True)
    class Meta:
        model = Order
        fields = '__all__'
        # 有太多只读的 就用read_only_fields
        read_only_fields = ['order_id','total_count','total_amount','status','user']

    def create(self, validated_data):
        """
        重写创建订单方法
        :param validated_data:用户传入的数据
        :return:
        """
    # 已知客户端要传递要结算的购物车商品id，支付方式，收货地址id
    # 根据客户端传来的数据 创建订单号
    # 生成订单编号 唯一的  (时间+格式化6位用户id+两位随机数)
        #先得到用户
        user = self.context['request'].user
      # 进行订单编号编写
        #格式化6位用户id
        user_id = '%06d' % user.id
        order_id = datetime.now().strftime('%Y%m%d%H%M%S')+user_id+'%02d' % randint(1,99)
        # 获取用户端输入的支付方式
        pay_method = validated_data.get('pay_method')
        # 获取用户端传来的收获地址di 得到详细的地址
        try:
            address = Address.objects.get(id=validated_data.get('address'))
        except Address.DoesNotExist:
            raise serializers.ValidationError('地址错误')
        # 字符串拼接生成收货地址文本数据   湖南省 长沙市 浏阳市 xxxx栋xxx 【xunter 收】 13412341234
        address_s = f'{address.province.name} {address.city.name} {address.district.name} {address.place} [{address.receiver} 收] {address.mobile}'

        # 开启事务，with关键字创建with的上下文协议 在其中创建事务对象 with里面的代码执行完毕后会自动关闭事务
        with transaction.atomic():
            # 创建回滚的保存点
            save_point = transaction.savepoint()
            try:
                # 初始化订单
                order = Order.objects.create(
                    order_id=order_id,
                    total_count=0,
                    total_amount=Decimal('0.00'),
                    pay_method=pay_method,
                    status=1 if pay_method==1 else 2,
                    address=address_s,
                    user = user
                )

                # 得到要结算的商品 也就是将购物车的商品依次拿出进行结算
                # 得到购物车中的商品id
                carts = validated_data.get('cart')
                for cart_id in carts:
                    # 一直对商品进行结算操作直到执行到更新订单表
                    while True:
                        # 核对用户的购物车中是否有该商品
                        try:
                            cart = ShoppingCart.objects.get(id=cart_id)
                        except ShoppingCart.DoesNotExist:
                            raise serializers.ValidationError('购物信息不存在')

                        # 得到购物车中的商品信息
                        commodity = cart.commodity

                        # 核对商品的库存数量和销量
                        origin_stock = commodity.stock
                        origin_sales = commodity.sales
                        if cart.commodity.stock > origin_stock:
                            raise serializers.ValidationError('库存不足')

                        # 商品库存充足可以购买 更新库存与销量
                        new_stock = origin_stock - cart.commodity.stock
                        new_sales = origin_sales + cart.number

                        # 加入乐观锁 在更新之前 先查询核对数据有没有发生变化 没有变化就更新数据
                        res = Commodity.objects.filter(id=commodity.id,stock=origin_stock).update(stock=new_stock,sales=new_sales)
                        # 如果没有成功执行更新操作 就continue对后面的操作进行跳过 不进行订单详情记录和更新订单表
                        if not res:
                            continue
                        # 订单详情记录
                        OrderGoods.objects.create(
                            number=cart.number,
                            price=commodity.price,
                            order=order,
                            commodity=commodity,
                        )

                        # 更新订单表
                        order.total_count += cart.number
                        order.total_amount += (commodity.price * cart.number)

                        break

                # 保存订单
                order.save()

                # 结算成功，删除已结算的购物车信息,
                ShoppingCart.objects.filter(id__in=carts).delete()

            except Exception as e:
                # 发生异常进行捕获并且回滚
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('e')
            else:
                #无异常  提交事务
                transaction.savepoint_commit(save_point)
        return order

class PaymentSerializer(ModelSerializer):
    class Meta:
        model = Payment
        fields = '__all__'






